package com.spring.security.app.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.security.core.properties.SecurityConstants;
import com.spring.security.core.support.ServerResponse;
import com.spring.security.core.support.ServerResponseEntity;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 默认的退出成功处理器
 *
 * @author seabed_moon
 */
@Log4j2
public class SpringLogoutSuccessHandler implements LogoutSuccessHandler {

    public SpringLogoutSuccessHandler(String signOutSuccessUrl) {
        this.signOutSuccessUrl = signOutSuccessUrl;
    }

    public SpringLogoutSuccessHandler() {
    }

    private String signOutSuccessUrl;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private TokenStore redisTokenStore;

    /**
     * (non-Javadoc)
     *
     * @see org.springframework.security.web.authentication.logout.LogoutSuccessHandler
     * LogoutSuccessHandler#onLogoutSuccess(javax.servlet.http.
     * HttpServletRequest, javax.servlet.http.HttpServletResponse,
     * org.springframework.security.core.Authentication)
     */
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException {
        String accessToken = request.getHeader(SecurityConstants.DEFAULT_PARAMETER_NAME_AUTHORIZATION).replace(SecurityConstants.DEFAULT_PARAMETER_NAME_BEARER, "");

        Assert.notNull(accessToken, "access_token is not null");

        OAuth2AccessToken oAuth2AccessToken = redisTokenStore.readAccessToken(accessToken);

        if (oAuth2AccessToken != null) {

            log.info("退出登录,access_token:{}", oAuth2AccessToken.getValue());

            redisTokenStore.removeAccessToken(oAuth2AccessToken);

            OAuth2RefreshToken oAuth2RefreshToken = oAuth2AccessToken.getRefreshToken();

            redisTokenStore.removeRefreshToken(oAuth2RefreshToken);

            redisTokenStore.removeAccessTokenUsingRefreshToken(oAuth2RefreshToken);

        }
        if (StringUtils.isBlank(signOutSuccessUrl)) {

            SecurityContextHolder.clearContext();

            response.setHeader(SecurityConstants.DEFAULT_PARAMETER_NAME_AUTHORIZATION, SecurityConstants.DEFAULT_BASIC_APP);
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            ServerResponse serverResponse = ServerResponseEntity.success(SecurityConstants.LOGOUT_SUCCESS_MSG, HttpStatus.OK.name());
            response.getWriter().write(objectMapper.writeValueAsString(serverResponse));

        } else {
            response.sendRedirect(signOutSuccessUrl);
        }
        log.info(SecurityConstants.LOGOUT_SUCCESS_MSG);
    }

}
